package cn.green.core.adapt.comps.field.type;

import cn.green.core.common.enums.field.ColumnType;
import cn.green.core.components.entity.ColumnLength;
import cn.green.core.components.entity.JoinInfo;
import cn.green.core.components.entity.QCondition;
import cn.green.core.components.field.FieldTypeCom;
import cn.green.core.components.field.t.OneToOne;
import cn.green.core.components.store.field.FieldTypeStore;
import cn.green.core.excel.model.Column;
import cn.green.core.front.model.Fetch;
import cn.green.core.front.model.Input;
import cn.green.core.front.model.Title;
import cn.green.core.model.QFieldModel;
import cn.green.core.model.QTableModel;
import cn.green.core.scanner.anno.comps.QTableComponent;
import cn.green.manage.cache.QCache;
import cn.green.utils.OrmAppUtils;
import com.alibaba.fastjson.JSONObject;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wang.yishu
 * @version 1.0
 * @className OneToOneType
 * @description 一对一的类型 为虚拟类型
 * @date 2025/5/14 14:49
 */
@QTableComponent
public class OneToOneType extends OneToOne {

    @Override
    public String fieldTypeName() {
        return "ORM_ONE_TO_ONE";
    }

    @Override
    public String fieldTypeCode() {
        return "ORM_ONE_TO_ONE";
    }

    @Override
    public ColumnType getColumnType(QFieldModel fieldModel) {
        return ColumnType.NONE;
    }

    @Override
    public ColumnLength getColumnLength(QFieldModel fieldModel) {
        return null;
    }

    @Override
    public boolean canBeSelected() {
        return false;
    }

    @Override
    public boolean isVirtual() {
        return true;
    }

    @Override
    public void parseRecord(JSONObject record, QFieldModel field) {
    }

    @Override
    public List<Input> inputs(QFieldModel field) {
        return Collections.emptyList();
    }

    @Override
    public List<Title> titles(QFieldModel field) {
        return Collections.emptyList();
    }

    @Override
    public QCache getCache() {
        return OrmAppUtils.getBean(QCache.class);
    }

    @Override
    public String getRelevantTableConfigKey() {
        return "relevantTable";
    }

    @Override
    public String getRelevantTableSourceConfigKey() {
        return "relevantTableSource";
    }

    @Override
    public String getRelevantTableSchemeConfigKey() {
        return "relevantTableSchema";
    }

    @Override
    public String getRelevantFieldsConfigKey() {
        return "relevantFields";
    }

    @Override
    public String getRelevantKeyConfigKey() {
        return "relevantKey";
    }

    @Override
    public List<Fetch> fetches(QTableModel table, QFieldModel field) {
        return Collections.emptyList();
    }

    @Override
    public List<Column> columns(QFieldModel field) {
        return Collections.emptyList();
    }

    @Override
    public List<JoinInfo> joinInfos(QTableModel table, QFieldModel field) {
        List<JoinInfo> rtn = new ArrayList<>();
        if (field.getConfigObj() != null) {
            QCache qCache = this.getCache();
            JSONObject configObj = (JSONObject) field.getConfigObj();
            //开始建造连接信息
            JoinInfo joinInfo = new JoinInfo();
            String joinName = configObj.getString("fieldName");
            List<QFieldModel> currentFields = qCache.getFieldsFromCache(table.getSourceName(), table.getSchemeName(), table.getTableName());
            QTableModel targetTable = qCache.getTableFromCache(configObj.getString("targetSource"), configObj.getString("targetScheme"), configObj.getString("targetTableName"));
            if (targetTable == null) {
                return Collections.emptyList();
            }
            List<QFieldModel> targetFields = qCache.getFieldsFromCache(targetTable.getSourceName(), targetTable.getSchemeName(), targetTable.getTableName());
            List<QFieldModel> foreignFields = targetFields.stream().filter(item -> {
                String fieldType = item.getFieldType();
                if (fieldType == null || fieldType.isEmpty()) {
                    return false;
                }
                FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                if (fieldTypeCom == null) {
                    return false;
                }
                return !fieldTypeCom.isVirtual();
            }).collect(Collectors.toList());
            JSONObject columnMap = configObj.getJSONObject("columnMap");
            if (columnMap == null) {
                return Collections.emptyList();
            }
            List<JoinInfo.JoinField> joinFields = new ArrayList<>();
            columnMap.forEach((k, v) -> {
                JoinInfo.JoinField joinField = new JoinInfo.JoinField();
                currentFields.stream().filter(item -> item.getFieldName().equals(k)).findFirst().ifPresent(joinField::setPrimaryTableField);
                foreignFields.stream().filter(item -> item.getFieldName().equals(v.toString())).findFirst().ifPresent(joinField::setForeignTableField);
                if (joinField.getForeignTableField() != null && joinField.getPrimaryTableField() != null) {
                    joinFields.add(joinField);
                }
            });
            joinInfo.setJoinName(joinName);
            joinInfo.setForeignTable(targetTable);
            joinInfo.setForeignFields(foreignFields);
            joinInfo.setJoinType(JoinInfo.JoinType.LEFT);//使用左连接
            joinInfo.setJoinFields(joinFields);
            rtn.add(joinInfo);
            for (QFieldModel targetField : targetFields) {
                String fieldType = targetField.getFieldType();
                if (fieldType == null || fieldType.isEmpty()) {
                    continue;
                }
                FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                if (fieldTypeCom == null) {
                    continue;
                }
                List<JoinInfo> joinInfos = fieldTypeCom.joinInfos(targetTable, targetField);
                if (joinInfos != null && !joinInfos.isEmpty()) {
                    rtn.addAll(joinInfos);
                }
            }
        }
        return rtn;
    }

    @Override
    public void formatRecord(JSONObject record, QFieldModel field) {
        //格式化数据
        JSONObject configObj = (JSONObject) field.getConfigObj();
        String fieldName = configObj.getString("fieldName");
        String targetSource = configObj.getString("targetSource");
        String targetScheme = configObj.getString("targetScheme");
        String targetTableName = configObj.getString("targetTableName");
        String dataKeyPrefix = fieldName + "." + targetSource + "." + targetScheme + "." + targetTableName + ".";
        JSONObject oneToOneData = new JSONObject();
        //Set<String> needRemove = new HashSet<>();
        Map<String, Object> d = new HashMap<>();
        //todo 这里需要修改。。。目标实体内部也可能关联了第三个实体
        record.forEach((k, v) -> {
            if (k.startsWith(dataKeyPrefix)) {
                //needRemove.add(k);
                oneToOneData.put(k.substring(dataKeyPrefix.length()).replaceAll("\\.", "@"), v);
                d.put(k.replaceAll("\\.", "@"), v);
            }
        });
        //needRemove.forEach(record::remove);
        record.put(fieldName, oneToOneData);
        record.putAll(d);
    }

    @Override
    public List<QCondition> conditions(QFieldModel field, JSONObject param) {
        String fieldName = field.getFieldName();
        String sourceName = field.getSourceName();
        String schemeName = field.getSchemeName();
        String tableName = field.getTableName();
        QCache qCache = OrmAppUtils.getBean(QCache.class);
        QTableModel tableFromCache = qCache.getTableFromCache(sourceName, schemeName, tableName);
        if (param.containsKey(fieldName)) {
            QCondition qCondition = new QCondition();
            qCondition.setConditionTable(tableFromCache);
            qCondition.setConditionField(field);
            qCondition.setType(QCondition.ConditionType.EQ);
            List<Object> values = new ArrayList<>();
            values.add(param.get(fieldName));
            qCondition.setValues(values);
            return Collections.singletonList(qCondition);
        }
        return Collections.emptyList();
    }


}
